﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Xml;
using MimiDouban.Test;

namespace MimiDouban.Extention
{
    public class DataStore
    {
        private static string FILENAME = "userinfo.txt";
        private static DataStore uniqeInstance = null;

        private XmlDocument doc;

        private DataStore()
        {
            doc = new XmlDocument();
            if (!File.Exists(FILENAME))
            {
                doc.AppendChild(doc.CreateElement("DataStore"));
            }
            else
            {
                try
                {
                    doc.Load(FILENAME);
                }
                catch (Exception ex)
                {
                    TestLog.getInstance().error("读取用户配置文件出错", ex);
                    doc.AppendChild(doc.CreateElement("DataStore"));
                }
            }
        }

        public static DataStore getInstance()
        {
            if (uniqeInstance == null)
            {
                uniqeInstance = new DataStore();
            }
            return uniqeInstance;
        }

        public void saveString(string key, string value)
        {
            lock (this)
            {
                try
                {
                    string className = getClassName();
                    XmlElement classElement = (XmlElement)doc.GetElementsByTagName(className)[0];

                    //MessageBox.Show("str " + key + ":" + className);

                    if (classElement == null)
                    {
                        classElement = doc.CreateElement(className);
                        doc.DocumentElement.AppendChild(classElement);
                    }

                    XmlElement valueElement = null;
                    XmlNodeList valueElements = classElement.GetElementsByTagName("*");
                    foreach (XmlNode xn in valueElements)
                    {
                        XmlElement xe = (XmlElement)xn;
                        if (xe.Attributes["Key"].Value == key)
                        {
                            valueElement = xe;
                            break;
                        }
                    }

                    if (valueElement == null)
                    {
                        valueElement = doc.CreateElement("Value");
                        XmlAttribute attr = doc.CreateAttribute("Key");
                        attr.Value = key;
                        valueElement.Attributes.Append(attr);
                        classElement.AppendChild(valueElement);
                    }

                    valueElement.InnerText = value;
                }
                catch (Exception e)
                {
                    TestLog.getInstance().error("存储数据失败", e);
                    BugReport.ShowReport("数据存储失败", e);
                }
            }
        }

        public string getString(string key)
        {
            lock (this)
            {
                try
                {
                    string className = getClassName();
                    XmlNodeList classElements = doc.GetElementsByTagName(className);

                    if (classElements.Count == 0)
                    {
                        return null;
                    }

                    XmlElement classElement = (XmlElement)classElements[0];


                    XmlElement valueElement = null;
                    XmlNodeList valueElements = classElement.GetElementsByTagName("*");
                    foreach (XmlNode xn in valueElements)
                    {
                        XmlElement xe = (XmlElement)xn;
                        if (xe.Attributes["Key"].Value == key)
                        {
                            valueElement = xe;
                            break;
                        }
                    }

                    if (valueElement == null)
                    {
                        return null;
                    }

                    return valueElement.InnerText;
                }
                catch (Exception e)
                {
                    TestLog.getInstance().error("读取数据失败", e);
                    BugReport.ShowReport("读取存储失败", e);
                }
                return null;
            }
        }

        public void saveStrings(string key, string[] values)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < values.Length - 1; i++)
            {
                sb.Append(values[i] + "@#$");
            }
            sb.Append(values[values.Length - 1]);
            saveString(key, sb.ToString());
        }      

        public string[] getStrings(string key)
        {
            string strs = getString(key);
            return strs.Split(new string[] { "@#$" }, StringSplitOptions.None);
        }

        public string[] getAllKeys()
        {
            lock (this)
            {
                try
                {
                    string className = getClassName();
                    XmlNodeList classElements = doc.GetElementsByTagName(className);

                    if (classElements.Count == 0)
                    {
                        return null;
                    }

                    XmlElement classElement = (XmlElement)classElements[0];

                    XmlNodeList valueElements = classElement.GetElementsByTagName("*");

                    string[] res = new string[valueElements.Count];
                    int i = 0;

                    foreach (XmlNode xn in valueElements)
                    {
                        XmlElement xe = (XmlElement)xn;
                        res[i++] = xe.Attributes["Key"].Value;
                    }
                    return res;

                }
                catch (Exception e)
                {
                    TestLog.getInstance().error("读取数据失败", e);
                    BugReport.ShowReport("读取存储失败", e);
                }
                return null;
            }
        }

        public double getDouble(string key)
        {
            string strDouble = this.getString(key);
            if (strDouble == null)
            {
                return double.NaN;
            }
            try
            {
                double res = double.Parse(strDouble);
                return res;
            }
            catch
            {
                return double.NaN;
            }
        }

        public void end()
        {
            XmlWriter writer = XmlWriter.Create(FILENAME);
            doc.WriteTo(writer);
            writer.Flush();
        }

        private string getClassName()
        {
            StackTrace st = new StackTrace();
            for (int i = 0; i < st.FrameCount; i++)
            {
                if (!st.GetFrame(i).GetMethod().DeclaringType.Equals(this.GetType()))
                {
                    return st.GetFrame(i).GetMethod().DeclaringType.ToString();
                }
            }
            return this.GetType().ToString();
        }

        
    }
}
